package com.pn.service.impl;

import com.alibaba.fastjson.JSON;
import com.pn.entity.Auth;
import com.pn.mapper.AuthMapper;
import com.pn.service.AuthService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 *
 */
// 指定缓存的名称(缓存的键的前缀)，一般是标注@CacheConfig类的全路径
@CacheConfig(cacheNames = "com.pn.service.impl.AuthServiceImpl")
@Service
public class AuthServiceImpl implements AuthService {

    @Resource
    private AuthMapper authMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Override
    public List<Auth> authTreeByUid(Integer userId) {

        // 先从redis中查询缓存的用户菜单树
        String authTreeJson = redisTemplate.opsForValue().get("authTree" + userId);
        if (StringUtils.hasText(authTreeJson)) { // 说明redis中有用户菜单树缓存
            // 将菜单树List<Auth>转的json串转回菜单树List<Auth>并返回
            return JSON.parseArray(authTreeJson, Auth.class);
        }

        /*
        说明redis中没有用户菜单树的缓存
         */
        // 查询用户权限下的所有菜单
        List<Auth> allAuthList = authMapper.findAuthByUid(userId);
        // 将所有菜单的List<Auth>转成菜单树List<Auth>
        List<Auth> authTreeList = allAuthToAuthTree(allAuthList, 0);
        // 向redis中缓存菜单树List<Auth>
        redisTemplate.opsForValue().set("authTree" + userId, JSON.toJSONString(authTreeList));
        return authTreeList;
    }

    // 查询方法上标注@Cacheable注解并指定缓存的键
    @Cacheable(key = "'all:authTree'")
    @Override
    public List<Auth> allAuthTree() {
        // 查询出所有权限菜单
        List<Auth> allAuth = authMapper.findAllAuth();
        return allAuthToAuthTree(allAuth, 0);
    }

    /**
     * 将所有菜单的List<Auth>转成菜单树List<Auth>的递归算法
     *
     * @param allAuthList 所有菜单
     * @param pid         父级菜单 pid（传0）
     * @return 菜单树
     */
    private List<Auth> allAuthToAuthTree(List<Auth> allAuthList, Integer pid) {

        // 查询出所有一级菜单
        List<Auth> firstLevelAuthList = new ArrayList<>();

        for (Auth auth : allAuthList) {
            if (auth.getParentId().equals(pid)) {
                firstLevelAuthList.add(auth);
            }
        }

        // 拿到每个一级菜单的所有二级菜单
        for (Auth firstAuth : firstLevelAuthList) {
            List<Auth> secondLevelAuthList = allAuthToAuthTree(allAuthList, firstAuth.getAuthId());
            firstAuth.setChildAuth(secondLevelAuthList);
        }
        return firstLevelAuthList;
    }

}
